//
//  OAuthAuthenticator.swift
//  SwiftCode
//
//  Created by yuhus on 2023/8/7.
//

import Alamofire

class OAuthAuthenticator: Authenticator {
  typealias Credential = OAuthCredential
  private static var refreshSession: Session?
  
  init(_ refreshSession: Session) {
    Self.refreshSession = refreshSession
  }
  
  /// 使用凭证对请求进行授权。
  func apply(_ credential: OAuthCredential, to urlRequest: inout URLRequest) {
    urlRequest.headers.add(name: "token", value: credential.accessToken)
  }
  
  /// 刷新凭证，并通过completion回调结果。
  func refresh(_ credential: OAuthCredential, for session: Alamofire.Session, completion: @escaping (Result<OAuthCredential, Error>) -> Void) {
    Timber.d(#function, credential)
    // 使用刷新令牌刷新凭据...然后使用新凭据调用 completion。
    // 新凭证将自动存储在“AuthenticationInterceptor”中。 未来的请求将使用新凭证通过“apply(_:to:)”方法进行身份验证。
    
    Self.refreshSession?.request(MetaService.visitorLogin)
      .responseDecodable(of: MetaModel.ResponseData<MetaModel.LoginInfo>.self) { response in
        guard let data = try? response.result.get().data else {
          completion(.failure(AuthenticationError.missingCredential))
          return
        }
        completion(.success(OAuthCredential(accessToken: data.token, refreshToken: "")))
      }
  }
  
  /// 根据`HTTPURLResponse`判断`URLRequest`是否因认证错误而失败。
  func didRequest(_ urlRequest: URLRequest, with response: HTTPURLResponse, failDueToAuthenticationError error: Error) -> Bool {
    Timber.d(#function)
    // 状态码401代表授权失败，此时应该返回true。
    guard response.statusCode != 401 else { return true }
    // 自定义401代表授权失败，此时应该返回true。
    return (error as? AFError)?.getValidationCode() == 401
  }
  
  /// 确定 URLRequest 是否通过 Credential 进行身份验证。
  func isRequest(_ urlRequest: URLRequest, authenticatedWith credential: OAuthCredential) -> Bool {
    Timber.d(#function)
    return true
  }
}
